#ifndef INC_UMLCANVAS_H
#define INC_UMLCANVAS_H

#include "../base/Observer.h"
#include "PointTranslator.h"

#include <QWidget>
#include <set>

class UMLObject;
class UMLDiagram;
class MouseListener;

class UMLCanvas : public QWidget
{
	Q_OBJECT;

	public:

		typedef std::set<UMLObject*> ObjSet;

		/*** CONSTRUCTORS ***/

		UMLCanvas(UMLDiagram *diagram, QWidget *parent = NULL);
		~UMLCanvas();

		/*** ACCESSORS ***/

		QSize minimumSizeHint() const;
		QSize sizeHint() const;

		UMLDiagram& diagram();

		const PointTranslator& trans() const;

		const MouseListener* mouseListener() const;
		void setMouseListener(MouseListener*);

		/*** SELECTION EDITING ***/

		/**
		 * Clears selection on all objects in the associated diagram.
		 *
		 * Note: only controller objects should call this.
		 */
		void clearSelection();

		/**
		 * Selects the specified object.
		 *
		 * Note: only controller objects should call this.
		 */
		void select(UMLObject* obj);

	signals:

		/**
		 * Emitted when the selection is changed. Newsel will contain the
		 * newly-selected object, which is not necessarily the whole selection.
		 * @param newsel the newly-selected object, or NULL if cleared
		 */
		void selectionChanged(UMLObject *newsel);

	protected:
		/*** PAINTING ***/
		void paintEvent(QPaintEvent*);

		/*** EVENTS ***/
		void mouseMoveEvent(QMouseEvent*);
		void mousePressEvent(QMouseEvent*);
		void mouseReleaseEvent(QMouseEvent*);

	private:

		class DiagramObserver : public Observer
		{
			public:
				/**
				 * This constructor guarantees that the canvas will only be
				 * stored, no data members will be accessed.
				 */
				DiagramObserver(UMLCanvas&);
				void update(Observable* o);

			private:
				UMLCanvas& _canvas;
		};

		UMLDiagram* _diagram; // init-checked
		PointTranslator _trans;

		MouseListener* _ml; // init-checked

		DiagramObserver _observer;

		ObjSet _selected;
		ObjSet _ghosts;
};

#endif // INC_UMLCANVAS_H
